package jgcp.worker;

/**
 * @author Peng Zhang
 * TaskQueue Class maintains a list of tasks which are assigned by master
 * TaskQueue Class build-in benchmark determines when to push waiting task to be executed
 * TaskQueue Class use sort algorithm to make sure high priority task can be executed first
 */
import java.util.*;

import jgcp.worker.monitor.WorkerMonitor;


public class TaskQueue implements TaskQueueSubject {
	
	private Queue <Task> taskqueue; // contain tasks
	private TaskQueueObserver observer; //the observer in observer pattern
	private WorkerMonitor monitor; // monitor can retrieve system statistics 
	private QueueThread pusher; // the thread pushes task to be processed
	
	public TaskQueue(TaskDispatcher patcher){
		taskqueue = new LinkedList <Task>();
		monitor = new WorkerMonitor();
		registerObserver(patcher);
		pusher= new QueueThread();
		//pusher.setDaemon(true);
		pusher.start();
		
		
	}
	
	
	public Task poll(){
		return taskqueue.poll();
	}
	
	public void addTask(Task task){
		taskqueue.add(task);
		sortQueue();
				
	}
	
	public void sortQueue(){
		
	}
	
	public void registerObserver(TaskQueueObserver o){
		
		observer = o;
	}
	public void removeObserver(TaskQueueObserver o){
		
		observer = null;
	}
	
	public  void notifyObserver(){
		
		observer.update(taskqueue.poll());
		
	}
	
	public void queueChanged(){
		notifyObserver();
	}
	
	
   /*
    *  capabilityCheck() used to determine whether the worker node is able to process new task 
    */
	public synchronized boolean capabilityCheck(){
		monitor.retrieveSystem();
		if(monitor.cpuUsage > 0.99 ){
			System.out.println("oops, have to wait...");
			return false;
		}
		else return true;
	}
	
	/*
	 *  return a ArrayList of current waiting tasks
	 */
	public  ArrayList  retrieveTasks(){
		Object[] o= taskqueue.toArray();
		ArrayList<Task> t = new ArrayList();
		int i;
		for(i=0;i<o.length;i++){
			t.add((Task)o[i]);
		}
		return t;
	}
	
	/*
	 *  cancel a task in waiting queue
	 */
	
	public boolean cancelTask(Task task){
		System.out.println("canceled");
		return taskqueue.remove(task);
	}
	
	
	/*
	 *  inner Class 
	 *  QueueThread Class checks worker node capacity iteratively and pushes task to be processed 
	 */
	class QueueThread extends Thread{
		public void run(){
			while(true){
				System.out.println(taskqueue.size());
				if(!taskqueue.isEmpty()&& capabilityCheck()){
					System.out.println("OK, you can move on");
					notifyObserver();
				}
			}
			
			
		}
	}
	
	
}
